package package1;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class TestForPackingJar {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		testPackClassFileToEclipseJarFile();
	}

	@SuppressWarnings("unused")
	private static void testPackClassFileToEclipseJarFile() throws IOException {
		String javaFileHome = "C:\\Users\\Alvin\\Desktop\\1\\test\\Hello2.java";
		String javaFileOffice = "C:\\Users\\alvin.wang\\Desktop\\1\\test\\Hello2.java";
		String jarName = "Hello";
		String javaFileAddr1 = javaFileHome;
		packClassFileToEclipseJarFile(jarName,javaFileAddr1);
	}

	/**
	 * every eclipse runnable jar file needs a package hierarchy 
	 * @param jarName
	 * @param javaFileAddr1
	 * @throws IOException
	 * Note, actually we don't need classHierarchy provided by user because we could read from java file
	 */
	private static void packClassFileToEclipseJarFile(String jarName, String javaFileAddr1) throws IOException {
		//1 = original; 2 = temporary
				
		//initializing data
		File javaFile1 = new File(javaFileAddr1);
		String javafolderAddr1 = javaFile1.getParent();
		String className = javaFile1.getName().replace(".java", "");
		String cmd;

		// extract the hierarchy information from the package line
		String buf; String folderHierarchy = "";
		BufferedReader br = new BufferedReader(new FileReader(javaFile1));
		while ((buf = br.readLine()) != null)
			if(buf.startsWith("package ")) folderHierarchy = extractText(buf.trim(), "package ", ";").replaceAll("\\.", "/");
		br.close();
		
		// compile java file in the local folder
		cmd = "javac " + quoteAddr(javaFile1.getAbsolutePath()) + " -d "+quoteAddr(getCurrentFolder().getAbsolutePath());
		run(cmd);
		
		//create MF file
		File MFFile = new File("manifest.mf");
		BufferedWriter bw = new BufferedWriter(new FileWriter(MFFile));
		bw.write("Main-Class: " + folderHierarchy+"/"+className + "\r\n");
		bw.close();
		
		//copy java file to class file folder(hierarchy folder)
		File javaFile2 =new File(getCurrentFolder()+"\\"+folderHierarchy+"\\"+className+".java");
		br = new BufferedReader(new FileReader(javaFile1));
		bw = new BufferedWriter(new FileWriter(javaFile2.getAbsolutePath()));
		while((buf = br.readLine())!=null) bw.write(buf+"\r\n");
		br.close();bw.close();
		
		// pack the jar file in the local folder with class file in remote folder
		//.zip is also ok
		cmd = "jar vcfm " + javafolderAddr1 + "\\" + jarName+".zip" + " " + MFFile.getPath() + " " +folderHierarchy;
		run(cmd);
		
		//to be checked!
		// delete all files in the temporary folder
		File classFile2 = new File(className + ".class");
		System.err.println("temp class file deleted " + (classFile2.delete() ? "successfully" : "failed"));
		System.err.println("temp MFFile file deleted " + (MFFile.delete() ? "successfully" : "failed"));
		File jarFile2 = new File(jarName);
		jarFile2.deleteOnExit();
		open(javafolderAddr1);
	}
	
	/**
	 * return folder address
	 * @return
	 */
	private static File getCurrentFolder() {
		String aa = new File(new File("a").getAbsolutePath()).getParent();
		return new File(aa);
	}

	public static String extractText(String str, String t1, String t2) {
		int t1Index = str.indexOf(t1);
		int t2Index = str.indexOf(t2);
		int t1Len = t1.length();
		return str.substring(t1Index+t1Len, t2Index);
	}
	
	public static void openCurrentFolder() throws IOException {
		open(getCurrentFolder().getAbsolutePath());
	}

	public static void open(String string) throws IOException {
		java.awt.Desktop.getDesktop().open(new File(string));
	}

	private static void run(String string) throws IOException {
		Process p = Runtime.getRuntime().exec(string);
		InputStream is1 = p.getInputStream();
		InputStream is2 = p.getErrorStream();
		BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));
		BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
		String b1,b2;
		StringBuffer sb1 = new StringBuffer();
		StringBuffer sb2 = new StringBuffer();
		while((b1=br1.readLine())!=null) sb1.append(b1);
		while((b2=br2.readLine())!=null) sb2.append(b2);
		br1.close();br2.close();
		if(!sb1.toString().equals(""))
			System.err.println("Process inputStream message:"+sb1.toString());
		if(!sb2.toString().equals(""))
			System.err.println("Process errorStream message:"+sb2.toString());
	}

	/**
	 * add '"' surround the path so CMD could recognize 
	 * @param string
	 * @return
	 */
	private static String quoteAddr(String string) {
		return "\""+string+"\"";
	}
}
